﻿using System;
using DevExpress.Xpo;
using System.Linq;
using System.Collections.Generic;
using DevExpress.Data.Filtering;

namespace Aij1.Model
{
    /// <summary>
    /// 文章基本类
    /// </summary>
    public class A_Article : XPObject
    {
        public A_Article(Session session)
            : base(session)
        {
            // This constructor is used when an object is loaded from a persistent storage.
            // Do not place any code here.
        }

        public override void AfterConstruction()
        {
            base.AfterConstruction();
            // Place here your initialization code.
        }

        string fTitle;
        [Size(100)]
        public string Title
        {
            get { return fTitle; }
            set { SetPropertyValue<string>("Title", ref fTitle, value); }
        }

        string fIntro;
        [Size(300)]
        public string Intro
        {
            get { return fIntro; }
            set { SetPropertyValue<string>("Intro", ref fIntro, value); }
        }

        S_Person fEditorId;
        public S_Person EditorId
        {
            get { return fEditorId; }
            set { SetPropertyValue<S_Person>("EditorId", ref fEditorId, value); }
        }

        DateTime fEditTime;
        public DateTime EditTime
        {
            get { return fEditTime; }
            set { SetPropertyValue<DateTime>("EditTime", ref fEditTime, value); }
        }

        DateTime fSetTopTime;
        public DateTime SetTopTime
        {
            get { return fSetTopTime; }
            set { SetPropertyValue<DateTime>("SetTopTime", ref fSetTopTime, value); }
        }

        A_Photo fSamplePhotoId;
        public A_Photo SamplePhotoId
        {
            get { return fSamplePhotoId; }
            set { SetPropertyValue<A_Photo>("SamplePhotoId", ref fSamplePhotoId, value); }
        }

        string fAuthor;
        [Size(50)]
        public string Author
        {
            get { return fAuthor; }
            set { SetPropertyValue<string>("Author", ref fAuthor, value); }
        }

        A_Category fCategoryId;
        public A_Category CategoryId
        {
            get { return fCategoryId; }
            set { SetPropertyValue<A_Category>("CategoryId", ref fCategoryId, value); }
        }

        [Association("A_P"), Aggregated]
        public XPCollection<A_Photo> Photos
        {
            get
            {
                var collection = GetCollection<A_Photo>("Photos");
                collection.Sorting = new SortingCollection(new SortProperty("OrderId", DevExpress.Xpo.DB.SortingDirection.Ascending),
        new SortProperty("Oid", DevExpress.Xpo.DB.SortingDirection.Ascending));
                return collection;
            }
        }

        DateTime fDisplayTime;
        /// <summary>
        /// 发表时间(在展示时显示的时间)
        /// </summary>
        [Indexed]
        public DateTime DisplayTime
        {
            get { return fDisplayTime; }
            set { SetPropertyValue<DateTime>("DisplayTime", ref fDisplayTime, value); }
        }

        ArticleStatusType fStatus;
        public ArticleStatusType Status
        {
            get { return fStatus; }
            set { SetPropertyValue<ArticleStatusType>("Status", ref fStatus, value); }
        }

        private XPDelayedProperty content = new XPDelayedProperty();
        [Size(SizeAttribute.Unlimited), Delayed("content", true)]
        public string Content
        {
            get { return (string)content.Value; }
            set { content.Value = value; }
        }

        ArticleType fAType;
        public ArticleType AType
        {
            get { return fAType; }
            set { SetPropertyValue<ArticleType>("AType", ref fAType, value); }
        }

        int fHitCount;
        public int HitCount
        {
            get { return fHitCount; }
            set { SetPropertyValue<int>("HitCount", ref fHitCount, value); }
        }

        string keywords;
        /// <summary>
        /// 以';'号隔开的关键字集合
        /// </summary>
        [NonPersistent]
        public string Keywords
        {
            get
            {
                if (keywords == null) keywords = String.Join(";", ArticleKeywords.Select(ak => ak.KeywordId.Title).ToArray());
                return keywords;
            }
            set
            {
                keywords = value;
            }
        }

        protected override void OnSaving()
        {
            GetKeywords();
            base.OnSaving();
        }

        /// <summary>
        /// 检查输入的关键词是否有'|'号隔开的同义词
        /// </summary>
        /// <returns></returns>
        List<A_Keyword> PickSynSet()
        {
            IEnumerable<string> newSet = Keywords.ToUpper().Split(';').Select(s => s.Trim()).Where(s => !String.IsNullOrEmpty(s));
            List<A_Keyword> keywords = new List<A_Keyword>();
            foreach (string syn in newSet)
            {
                string[] syns = syn.Split('|').Select(s => s.Trim()).Where(s => !String.IsNullOrEmpty(s)).ToArray();
                if (syns.Length == 0) continue;
                string mainKey = syns[0];
                if (String.IsNullOrEmpty(mainKey)) continue;
                A_Keyword key = Session.FindObject<A_Keyword>(CriteriaOperator.Parse("Title=?", mainKey))
                ?? new A_Keyword(Session)
                {
                    Title = mainKey,
                };
                key.InUse = true;
                while (key.ParentId != null) key = key.ParentId;
                key.Save();

                foreach (string subKey in syns.Skip(1))
                {
                    A_Keyword sub = Session.FindObject<A_Keyword>(CriteriaOperator.Parse("Title=?", subKey))
                    ?? new A_Keyword(Session)
                    {
                        Title = subKey,
                    };

                    sub.ParentId = key;
                    sub.InUse = true;
                    sub.Save();
                }

                keywords.Add(key);
            }

            return keywords;
        }

        void GetKeywords()
        {
            IEnumerable<A_Keyword> newSet = PickSynSet();
            IEnumerable<A_Keyword> oldSet = ArticleKeywords.Select(ak => ak.KeywordId);
            IEnumerable<A_Keyword> inSet = newSet.Except(oldSet).ToArray();
            IEnumerable<A_Keyword> outSet = oldSet.Except(newSet).ToArray();

            //删除不在新词列表中的原有文章-关键词关联记录
            foreach (var outKey in outSet)
            {
                ArticleKeywords.First(ak => ak.KeywordId == outKey).Delete();
            }

            //新增不在原有文章-关键词表中的新词
            foreach (var inKey in inSet)
            {
                A_ArticleKeyword ak = new A_ArticleKeyword(Session)
                {
                    ArticleId = this,
                    KeywordId = inKey,
                };
            }

            //删除非主词的同义词，只保留主词
            foreach (A_ArticleKeyword ak in ArticleKeywords.ToArray())
            {
                if (ak.KeywordId.ParentId != null)
                {
                    if (ArticleKeywords.FirstOrDefault(ak1 => ak1.KeywordId == ak.KeywordId.ParentId) == null)
                    {
                        ArticleKeywords.Add(new A_ArticleKeyword(Session)
                        {
                            KeywordId = ak.KeywordId.ParentId,
                            ArticleId = this,
                        });
                    }
                    ak.Delete();
                }
            }
        }

        string fSourceUrl;
        /// <summary>
        /// 来源网址
        /// </summary>
        [Size(200)]
        public string SourceUrl
        {
            get { return fSourceUrl; }
            set { SetPropertyValue<string>("SourceUrl", ref fSourceUrl, value); }
        }

        [Association("A_AK"), Aggregated]
        public XPCollection<A_ArticleKeyword> ArticleKeywords
        {
            get { return GetCollection<A_ArticleKeyword>("ArticleKeywords"); }
        }
    }
}